package com.arpa.wms.service;

import com.arpa.core.web.Result;
import com.arpa.oms.domain.entity.OmsAllocation;
import com.arpa.oms.domain.entity.Sale;
import com.arpa.wms.domain.dto.*;
import com.arpa.wms.domain.entity.Delivery;
import com.arpa.wms.domain.entity.Outbound;
import com.arpa.wms.domain.entity.OutboundItem;
import com.arpa.wms.domain.entity.Picking;
import com.arpa.wms.domain.vo.DeliveryVO;
import com.arpa.wms.domain.vo.WaveQueryGoodsVO;
import com.baomidou.mybatisplus.extension.service.IService;
import com.taobao.api.ApiException;


import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * 出货单 服务类
 * </p>
 *
 * @author LEO
 * @since 2020-08-07
 */
public interface IDeliveryService extends IService<Delivery> {

	Result confirm(String code,String groupCode);

	void saveByOmsAllocation(OmsAllocation omsAllocation);

	/**
	 * 根据code更新实体
	 * @param entity
	 * @return
	 */
	int updateByCode(Delivery entity);

	/**
	 * 查询列表
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryList(DeliveryDTO deliveryDTO);

	/**
	 * 查询合计,包含总数
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO queryListSum(DeliveryDTO deliveryDTO);

	/**
	 * 查询合计,包含总数
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO queryListTotal(DeliveryDTO deliveryDTO);

	/**
	 * 查询列表，关联item表，用于判断订单明细中是否包含某些商品
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryListJoinItem(DeliveryDTO deliveryDTO);
	List<DeliveryVO> queryWaveListJoinItem(DeliveryDTO deliveryDTO);
	/**
	 * 查询合计,包含总数，关联item表，用于判断订单明细中是否包含某些商品
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO queryListJoinItemSum(DeliveryDTO deliveryDTO);

	DeliveryVO queryWaveListJoinItemSum(DeliveryDTO deliveryDTO);


	/**
	 *  @author: Allen chen
	 *  @Date: 2020/8/18 9:51
	 *  @Description:
	 */
	Result saveWithGoods(Delivery entity);

	/**
	 *  @author: Allen chen
	 *  @Date: 2020/8/19 13:57
	 *  @Description: 计算出货单商品数量
	 */
	BigDecimal getTotalNum(Delivery outboundWithGoods);


	/**
	 * 取消分配
	 * @param delivery
	 * @return
	 */
	Result cancelDistribution(DeliveryVO delivery);

	/**
	 * 更新发货数量
	 * @param deliveryDTO
	 * @return
	 */
	int updateSendNum(DeliveryDTO deliveryDTO);

	/**
	 * 拣货确认时更新订单拣货数量
	 * @param entity
	 * @return
	 */
	int updatePickingQuantity(Picking entity);

	/**
	 * 查询可退货订单列表
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryCanRefundList(DeliveryDTO deliveryDTO);

	/**
	 * 作废订单
	 * @param code
	 * @return
	 */
	Result blank(String code);

	DeliveryVO getDeliveryVoByEntity(Delivery delivery);

	/**
	 * 调整发货单分配数量
	 * @param deliveryDTO
	 * @return
	 */
	int adjustDistributionNum(DeliveryDTO deliveryDTO);

	DeliveryVO getVOByCode(String code);

	/**
	 * @description
	 * 根据分配确认单中的拣货数量更新主单的拣货数量
	 * @author xuyang
	 * @date 2020/10/26 11:07
	 * @param deliveryCode:
	 **/
	int updatePickNumByDistributionData(String deliveryCode);


	/**
	 * 更新退货数量
	 * @param deliveryCode
	 */
	void updateRefundQuantity(String deliveryCode);

	/**
	 * 发货单根据来源单类型，回填来源单、来源单明细的实际出库数量
	 * @param delivery
	 */
	void updateWmsSourceQuantity(Delivery delivery, Outbound outbound, List<OutboundItem> outboundItems);

	/**
	 * @description
	 * 发货单在出库操作后的操作，如回填oms单据
	 * @author xuyang
	 * @date 2020/12/15 13:54
	 * @param outbound:
	 * @param outboundItems:
	 **/
	void afterOutbound(Outbound outbound, List<OutboundItem> outboundItems);

	/**
	 * @description
	 * 发货退货单主单及明细
	 * @author xuyang
	 * @date 2020/12/15 19:29
	 * @param code:
	 **/
	DeliveryVO getRefundVOByCode(String code);

	/**
	 * @description
	 * 保存/提交 发货退货单
	 * @author xuyang
	 * @date 2020/12/18 9:16
	 * @param entity:
	 * @param submitFlag: 是否提交；true： 提交操作；false：本地保存操作
	 **/
	Result refundSaveOrSubmit(Delivery entity, boolean submitFlag);


	/**
	 * 导入数据回显
	 * @param deliveryExcelDTOList
	 * @return
	 */
	List<DeliveryExcelDTO> deliveryView(List<DeliveryExcelDTO> deliveryExcelDTOList);

	/**
	 * 导入数据
	 */
	void deliveryImport();

	/**
	 * 部分确认
	 * @param entity
	 */
	void partConfirm(Delivery entity);

	/**
	 * 出库复核时更新发货单分配数量，如缺货登记后需要调整实际分配数量
	 * @param deliveryCode
	 * @return
	 */
	int updateDistributionQuantityForOutboundRecheck(String deliveryCode,String groupCode);

	/**
	 * 判断发货单状态为“已分配”，且总发货数量=分配数量
	 * @param deliveryCode
	 * @return
	 */
	boolean isDeliveryAndOutboundAllFinish(String deliveryCode,String groupCode);

	/**
	 * 判断发货单状态为“已分配”，且总发货数量=分配数量
	 * @param delivery
	 * @return
	 */
	boolean isDeliveryAndOutboundAllFinish(Delivery delivery);

	/**
	 * 发货单分配量为0则更新状态为“待分配”
	 * @param deliveryCode
	 */
	void updateDeliveryStatusIfEmptyDistribution(String deliveryCode,String groupCode);

	/**
	 * 订单处理生成波次单号、拣货单、拣货单明细
	 * @param deliveryDTO
	 */
	Map<String, Object>  saveWave(DeliveryDTO deliveryDTO);

	/**
	 * 解除发货单与波次的关系
	 * @param delivery
	 */
	int releaseRelation(Delivery delivery);

	/**
	 * 打印发货单 快递面单
	 * @param deliveryCodes
	 * @return
	 */
	List<DeliveryVO> printExpress(List<String> deliveryCodes);

	/**
	 * 波次查询总数
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO queryWaveListSum(DeliveryDTO deliveryDTO);

	/**
	 * 波次查询
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryWaveList(DeliveryDTO deliveryDTO);

	/**
	 * 批量拣货完成，更新发货单状态
	 * @param pickingCode
	 */
	void updateStatusByPickingCode(String pickingCode);

	/**
	 * 根据波次单号修改发货单状态
	 * @param wavePickingCode
	 * @param status
	 */
	void updateStatusByWavePickingCode(String wavePickingCode,String status,String groupCode);

	/**
	 * 与queryList方法一致，但没有分页限制
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryAllList(DeliveryDTO deliveryDTO);

	/**
	 * 批量生成拣货单
	 * @param codes
	 * @return
	 */
	Map<String, Object> batchGeneratePicking(List<String> codes);

	List<Map<String, Object>> getEnumList(String type);

	/**
	 * 获取面单号
	 * @param code
	 *//*

    void getWaybillCode(String code);
*/

	/**
	 * 批量获取面单号
	 * @param deliveryCodes
	 */
	String batchGetWaybillCode(List<String> deliveryCodes);

	void updateStatusByWavePickingCode(String wavePickingCode, Integer type);

	/**
	 * 根据波次号，更新发货单拣货数量
	 * @param wavePickingCode
	 * @return
	 */
	int updatePickingQuantityByWavePickingCode(String wavePickingCode,String groupCode);


	/**
	 * 出库确认获取波次内所有订单的状态分组，用来判断出库单状态
	 * @author liuxr
	 * @date 2021/4/23 17:36
	 * @param wavePickingCode 波次号
	 * @return java.util.List<java.lang.String>
	 */
	Set<String> findDeliveryStatusForConfirmDelivery(String wavePickingCode,String groupCode);


	/**
	 * 出库确认获取所有符合条件的订单
	 * 根据波次号获取待出库、面单号不为空、计划数量=复核数量的订单号
	 * @author liuxr
	 * @date 2021/4/23 17:35
	 * @param wavePickingCode 波次号
	 * @return java.util.List<com.arpa.wms.domain.entity.Delivery>
	 */
	List<Delivery> findDeliveryForConfirmDelivery(String wavePickingCode,String groupCode);



	/**
	 * 发货单确认消息, 用于订单更新奇门单据
	 * @param delivery
	 * @return
	 */
	boolean deliveryorderConfirmForOutCheck(Delivery delivery) throws ApiException;

	/**
	 * 根据订单的分配单减少临时库存
	 * @param deliveryCode
	 */
	@Deprecated
	void releaseTempInv(String deliveryCode);

	/**
	 * 更新订单面单信息
	 * @param code 发货单标识
	 * @param wayBillCode 面单号
	 * @param signature 验签
	 * @param url 模板url
	 */
	void updateWayBillCode(String code,
						   String wayBillCode,
						   String signature,
						   String url,String printData,String routeCode, String groupCode);

	/**
	 * 更新订单备注
	 * @param deliveryCodes 订单号集合
	 * @param remarks
	 */
	void updateRemarks(List<String> deliveryCodes, String remarks, String groupCode);

	/**
	 * 根据订单号统计承运商数量
	 * @param codes 订单号
	 * @return
	 */
	int countLogistics(List<String> codes);
	/**
	 * 根据订单号统计货主数量
	 * @param codes 订单号
	 * @return
	 */
	int countShipment(List<String> codes);

	/**
	 * 根据订单号统计波次数量
	 *
	 * @param codes 订单号
	 * @param maxOrderQuantity 单波次最大订单数
	 * @return
	 */
	int countWave(List<String> codes, Integer maxOrderQuantity);

	/**
	 * 生成波次
	 *
	 * @param codes 订单号
	 * @param maxOrderQuantity 单波次最大订单数
	 * @param isReview 是否复核：0不复核，1复核
	 * @return
	 */
	void genWave(List<String> codes, Integer maxOrderQuantity,String temporaryCode,int isReview);

	/**
	 * 更新波次生成状态
	 * @param codes 订单号
	 */
	String updateWaveStatus(List<String> codes);

	/**
	 * 订单处理页面-商品查询总数
	 * @param waveQueryGoodsDTO
	 * @return
	 */
	WaveQueryGoodsVO waveQueryGoodsSum(WaveQueryGoodsDTO waveQueryGoodsDTO);

	/**
	 * 订单处理页面-商品查询结果
	 * @param waveQueryGoodsDTO
	 * @return
	 */
	List<WaveQueryGoodsVO> waveQueryGoods(WaveQueryGoodsDTO waveQueryGoodsDTO);

	/**
	 * 订单处理页面-爆品商品查询总数
	 * @param waveQueryGoodsDTO
	 * @return
	 */
	WaveQueryGoodsVO waveQueryHotGoodsSum(WaveQueryGoodsDTO waveQueryGoodsDTO);


	/**
	 * 订单处理页面-爆品商品查询结果
	 * @param waveQueryGoodsDTO
	 * @return
	 */
	List<WaveQueryGoodsVO> waveQueryHotGoods(WaveQueryGoodsDTO waveQueryGoodsDTO);

	/**
	 * 当订单不需要复核操作时，需要在生成出库单时更新订单状态
	 * @param wavePickingCode
	 * @return
	 */
	int updateStatusWithoutRecheck(String wavePickingCode);

	/**
	 * 订单需要复核操作时，需要再生成出库单时更新订单状态
	 * @param wavePickingCode
	 * @return
	 */
	int updateStatusWithRecheck(String wavePickingCode,String groupCode);

	/**
	 * 更新订单状态和数量
	 * @param wavePickingCode
	 * @return
	 */
	boolean updateStatusAndQuantity(String wavePickingCode);

	/**
	 * 更新复核数量
	 * @param deliveryCode
	 */
	int updateRecheckQuantity( String deliveryCode);

	/**
	 * 根据订单的计划数量与（订单的拣货数量和缺货数量之间的关系）更新订单状态
	 * @param delivery
	 * @return
	 */
	void updateDelvieryStatus(Delivery delivery);

	/**
	 * 根据波次号和订单状态查询订单信息
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryDeliveryList(DeliveryDTO deliveryDTO);

	/**
	 * 根据订单code查询订单信息
	 * @param deliveryCode
	 * @param status
	 * @param goodsBarCode
	 * @return
	 */
	DeliveryVO getDeliveryByCode(String deliveryCode,String status,String goodsBarCode);

	/**
	 * @description
	 * 根据拣货量与复核量+退减量的比较，尝试更新明细的状态
	 * @author xuyang
	 * @date 2020/10/29 8:55
	 * @param itemCode:
	 * @param status:
	 **/
	int updateStatusIfFinishRecheck(String itemCode, String status);

	/**
	 * 订单清空运单号
	 * @author liuxr
	 * @date 2021/5/10 15:39
	 * @param deliveryCode
	 */
	void waybillDiscard(String deliveryCode);

	/**
	 * 根据波次号统计订单计划总量
	 * @author liuxr
	 * @date 2021/5/15 9:56
	 * @param wavePickingCode 波次号
	 * @return java.math.BigDecimal 订单计划总量
	 */
	BigDecimal getTotalNumByWavePickingCode(String wavePickingCode);

	/**
	 * 根据波次号统计订单商品种类总量
	 * @author liuxr
	 * @date 2021/5/15 9:56
	 * @param wavePickingCode 波次号
	 * @return java.math.BigDecimal 订单商品种类总量
	 */
	BigDecimal getGoodsTotalNumByWavePickingCode(String wavePickingCode);

    /**
     * 根据波次号更新发货明细的复核数量
     * @param wavePickingCode
     * @return
     */
    int updateRecheckQuantityByWavePickingCode(String wavePickingCode);
    /**
     * 更新复核数量和状态
     * @param deliveryCodes
     * @param status
     */
    void updateRecheckQuantityAndStatus(Set<String> deliveryCodes, String status);


    void updatePrintCount(String deliveryCode);
    void batchUpdatePrintCount(List<DeliveryDTO> codes);

    void batchUpdatePrintCount(List<String> codes,Integer printNum);


	/**
	 * 波次拣货确认，不需要复核操作时，自动更新订单复核数量及状态
	 * @param wavePickingCode 波次号
	 */
	void autoUpdateStatusAndRecheckQuantity(String wavePickingCode,String groupCode);

	/**
	 * 复核出库确认，自动更新订单复核数量及状态
	 * @param deliveryDistributionDTO
	 */
	void autoUpdateRecheckQuantityByCodes(DeliveryDistributionDTO deliveryDistributionDTO);


	/**
	 * 波次拣货确认，不需要复核操作时，自动更新订单出库数量及状态
	 * @param deliveryCodes 订单号
	 */
	void autoUpdateStatusAndSendQuantity(Set<String> deliveryCodes,String groupCode);

	/**
	 * 波次拣货缺货登记，更新订单分配明细、订单明细缺货数量、拣货数量和状态
	 * @author liuxr
	 * @date 2021/6/5 17:05
	 * @param refundQuantity 缺货数量
	 * @param deliveryDistributionCode 分配明细标识
	 * @param deliveryItemCode 订单明细标识
	 */
    void updateItemsOutStockQuantity(BigDecimal refundQuantity, String deliveryDistributionCode, String deliveryItemCode);
	/**
	 * 波次拣货缺货登记，更新订单缺货数量
	 * @author liuxr
	 * @date 2021/6/5 17:05
	 * @param deliveryCode 订单号
	 */
    void updateOutStockQuantity( String deliveryCode);

	/**
	 * 查询合计,异常订单总数
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO queryAbnormalListSum(DeliveryDTO deliveryDTO);

	/**
	 * 查询异常单列表
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryAbnormalList(DeliveryDTO deliveryDTO);

	/**
	 * 出库订单数量统计 Visual
	 * @return
	 */
	String outboundQuantityTrend(String time, String status);

	/**
	 * 根据波次单号修改发货单状态
	 * @param deliveryCode
	 * @param status
	 */
	void updateStatusByCode(String deliveryCode,String status,String groupCode);

	/**
	 * 查询合计,待打包订单总数
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO queryWaitingPackingOrderListSum(DeliveryDTO deliveryDTO);




	/**
	 * 根据codes更新实体
	 * @param dto
	 * @return
	 */
	int updateByCodes(DeliveryDTO dto);

	/**
	 * 发货单打包任务分组信息
	 *  [shipmentCode:,carrierCode:,carrierName:,count:,totalNum:]
	 * @param codes 订单号
	 * @return
	 */
	List<Map<String,Object>> queryPackTaskGroupInfo(List<String> codes);

	/**
	 * 根据波次获取预打包订单 列表
	 *
	 * @param wavePickingCode 波次号
	 * @return
	 */
	List<DeliveryVO> queryDeliveryListByWavingCode(String wavePickingCode);

	/**
	 * 根据订单号更新发货单的复核数量
	 * @param code
	 * @return
	 */
	int updateRecheckQuantityByCode(String code,String groupCode);

	/**
	 * @description
	 * 根据波次号，更新复合数量和状态
	 * @author rfwang
	 * @date 2021年7月16日
	 * @param wavePickingCode:
	 **/
	int updateRecheckQuantityAndStatsuByWavePickingCode(String wavePickingCode);

	/**
	 * @description
	 * 根据oms销售单生成wms的发货单
	 * @author xuyang
	 * @date 2020/11/9 9:44
	 * @param sale:
	 **/
	Delivery createByOmsSale(Sale sale);

	/**
	 * @description
	 * 订单发货确认
	 * @author xuyang
	 * @date 2021/8/25 13:13
	 * @param saleCode:
	 **/
	Result deliveryConfirm(String saleCode,String wavePickingCode);

	/**
	 * @description  更新作废单状态
	 * @author rfwang
	 * @date 2021/11/3 18:36
	 **/
	void updateCanceledDeliveryStatus(String groupCode,List<String> warehouseCodeList,List<String> shipmentCodeList);


	/**
	 * 波次下的订单数量
	 * @param wavePickingCode
	 * @return
	 */
	int cancelWaveTipsPrompt(String wavePickingCode);

	/**
	 * 订单导出
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> importDelivery(DeliveryDTO deliveryDTO);

	/**
	 * 查询导出数据合计,包含总数
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO importDeliveryTotal(DeliveryDTO deliveryDTO);

	/**
	 * 重构入参
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryDTO constructQueryParams(DeliveryDTO deliveryDTO);

	/**
	 * 根据波次号更新面单的打印次数
	 * @param wavePickingCode
	 * @return
	 */
	void updatePrintCountByWavePickingCode(String wavePickingCode,String groupCode);

	/**
	 * 更新获取面单失败原因
	 * @param deliveryCodes
	 * @return
	 */
	boolean updateFailureReasonOfGetWaybillCode(List<String> deliveryCodes,String reason,String groupCode);



	/**
	 * 更改承运商 校验订单 并 修改订单
	 * @param deliveryCodes
	 * @param carrierCode
	 */
    void checkDelivery(List<String> deliveryCodes,String carrierCode);

	/**
	 * 订单处理查询合计,包含总数
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryVO queryWaveListTotal(DeliveryDTO deliveryDTO);

	/**
	 * 校验是否是同一个仓库下的订单
	 * @param codes
	 * @return
	 */
	boolean validateSameWarehouseCode(List<String> codes);

	/**
	 * 获取积压订单数量(即未出库完成的订单数量)
	 * @return
	 */
	Result getBacklogOrderNum();

	/**
	 * 重新构造查询入参
	 * @param deliveryDTO
	 * @return
	 */
	DeliveryDTO constructParams(DeliveryDTO deliveryDTO);

	/**
	 * 根据订单号或者面单号获取订单信息(即未出库完成的订单数量)
	 * @return
	 */
	Result getDeliveryInfoByOrderCode(DeliveryDTO deliveryDTO);

	/**
	 * 按照库位汇总的商品数量，更新订单的复核数量
	 * @return
	 */
	int updateDeliveryRecheckQuantity(DeliveryItemDTO deliveryItemDTO);

	/**
	 * 根据pn码查询商品条码
	 * @author rfwang
	 * @date 2022/3/18 13:13
	 * @param deliveryCode 出库单号
	 * @param goodsBarCode 出库明细单号
	 *@param  groupCode 组织机构
	 */
	Result getGoodsCodeByPn(String deliveryCode,String goodsBarCode,String groupCode);

	/**
	 * 查询列表
	 * @param deliveryDTO
	 * @return
	 */
	List<DeliveryVO> queryBdList(DeliveryDTO deliveryDTO);

	/**
	 * 获取订单来源平台信息
	 * @param
	 * @return
	 */
	List<DeliveryVO> chooseSourcePlatformList();



}
